package com.ddwl.gate.util;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.*;

import javax.annotation.Resource;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import com.alibaba.fastjson.JSON;
import com.ddwl.common.util.BeanConverUtils;
import com.ddwl.gate.dao.IdCardVerifyRecordDao;
import com.ddwl.gate.model.IdCardVerifyRecord;
import com.ddwl.schema.bo.gate.IDOCRAuthBo;
import com.ddwl.schema.bo.gate.TencentOCRAuthBo;
import com.ddwl.common.constant.OcrEnum;
import com.ddwl.schema.vo.gate.BankCardVo;
import com.ddwl.schema.vo.gate.BizLicenseVo;
import com.ddwl.schema.vo.gate.IdCardVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
//import sun.misc.BASE64Encoder;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import java.util.Base64;
import com.tencentcloudapi.ocr.v20181119.OcrClient;
import com.tencentcloudapi.ocr.v20181119.models.*;
import tk.mybatis.mapper.util.StringUtil;;

/**
 * 腾讯云人脸识别
 * @author wenbin
 */
@Service
@RefreshScope
@Slf4j
public class TencentOCRUtil {

    @Resource
    private IdCardVerifyRecordDao idCardVerifyRecordDao;
    @Value("${TXCLOUD.FACEOCR.SecretID}")
    private String secretId;
    @Value("${TXCLOUD.FACEOCR.SecretKey}")
    private String secretKey;
    @Value("${TXCLOUD.IDOCR.SecretId}")
    private String idSecretId;
    @Value("${TXCLOUD.IDOCR.SecretKey}")
    private String idSecretKey;
    /**
     *人脸识别认证url
     */
    private String faceVerifyUrl="http://service-0ob4jwmn-1300755093.ap-beijing.apigateway.myqcloud.com/release/efficient/idfaceIdentity";

      /**
     *身份证2要素识别认证url
     */
    private String verifyUrl="http://service-ig4o8nzj-1300755093.ap-beijing.apigateway.myqcloud.com/release/idcard/VerifyIdcardv2";


      /**
     *身份证OCR识别
     */
    private String OCRVerifyUrl="ocr.tencentcloudapi.com";



    public String calcAuthorization(String source, String datetime)
            throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
        String signStr = "x-date: " + datetime + "\n" + "x-source: " + source;
        Mac mac = Mac.getInstance("HmacSHA1");
        Key sKey = new SecretKeySpec(secretKey.getBytes("UTF-8"), mac.getAlgorithm());
        mac.init(sKey);
        byte[] hash = mac.doFinal(signStr.getBytes("UTF-8"));
        //String sig = new BASE64Encoder().encode(hash);
        String sig = Base64.getEncoder().encodeToString(Objects.requireNonNull(hash));


        String auth = "hmac id=\"" + secretId + "\", algorithm=\"hmac-sha1\", headers=\"x-date x-source\", signature=\"" + sig + "\"";
        return auth;
    }

    public String urlencode(Map<?, ?> map) throws UnsupportedEncodingException {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<?, ?> entry : map.entrySet()) {
            if (sb.length() > 0) {
                sb.append("&");
            }
            sb.append(String.format("%s=%s",
                    URLEncoder.encode(entry.getKey().toString(), "UTF-8"),
                    URLEncoder.encode(entry.getValue().toString(), "UTF-8")
            ));
        }
        return sb.toString();
    }

    public String ImageToBase64(String imgPath) {
        byte[] data = null;
        // 读取图片字节数组
        try {
            InputStream in = new FileInputStream(imgPath);
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 对字节数组Base64编码
        //BASE64Encoder encoder = new BASE64Encoder();
        // 返回Base64编码过的字节数组字符串
        String ss = Base64.getEncoder().encodeToString(Objects.requireNonNull(data));
        //String ss= encoder.encode(Objects.requireNonNull(data));
        System.out.print(ss);
        return ss;
    }






    public String checkIdCard(TencentOCRAuthBo bo) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
        String source = "market";

        Calendar cd = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
        sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
        String datetime = sdf.format(cd.getTime());
        // 签名
        String auth = calcAuthorization(source, datetime);
        // 请求方法
        String method = "POST";
        // 请求头
        Map<String, String> headers = new HashMap<String, String>();
        headers.put("X-Source", source);
        headers.put("X-Date", datetime);
        headers.put("Authorization", auth);

        // 查询参数
        Map<String, String> queryParams = new HashMap<String, String>();
        if (bo.getIsFaceVerify()==0){
            queryParams.put("cardNo", bo.getNumber());
            queryParams.put("realName", bo.getName());
        }

        // body参数
        Map<String, String> bodyParams = new HashMap<String, String>();
        if (bo.getIsFaceVerify()==1){
            bodyParams.put("base64Str", ImageToBase64(bo.getBase64Str()));
            bodyParams.put("liveChk", bo.getLiveChk());
            bodyParams.put("name", bo.getName());
            bodyParams.put("number", bo.getNumber());
            bodyParams.put("Threshold", bo.getThreshold());
        }
        // url参数拼接
        String url = "";
        if (bo.getIsFaceVerify()==0){
            url=verifyUrl;
        }else {
            url=faceVerifyUrl;
        }
        if (!queryParams.isEmpty()) {
            url += "?" + urlencode(queryParams);
        }

        BufferedReader in = null;
        try {
            URL realUrl = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(5000);
            conn.setRequestMethod(method);

            // request headers
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                conn.setRequestProperty(entry.getKey(), entry.getValue());
            }

            // request body
            Map<String, Boolean> methods = new HashMap<>();
            methods.put("POST", true);
            methods.put("PUT", true);
            methods.put("PATCH", true);
            Boolean hasBody = methods.get(method);
            if (hasBody != null) {
                conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

                conn.setDoOutput(true);
                DataOutputStream out = new DataOutputStream(conn.getOutputStream());
                out.writeBytes(urlencode(bodyParams));
                out.flush();
                out.close();
            }
            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            String result = "";
            while ((line = in.readLine()) != null) {
                result += line;
            }
            //腾讯云校验记录
            IdCardVerifyRecord idCardVerifyRecord=new IdCardVerifyRecord();
            idCardVerifyRecord.setRequest(JSON.toJSONString(bo));
            idCardVerifyRecord.setIsFaceVerify(bo.getIsFaceVerify());
            idCardVerifyRecord.setResponse(result);
            idCardVerifyRecord.setDatetime(datetime);
            ((TencentOCRUtil) AopContext.currentProxy()).recordNew(idCardVerifyRecord);
            return result;
        } catch (Exception e) {
            System.out.println(e);
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return null;
    }

    public IdCardVo idDCardOCR(IDOCRAuthBo bo){
        try{
            Credential cred = new Credential(idSecretId, idSecretKey);

            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint(OCRVerifyUrl);

            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);

            OcrClient client = new OcrClient(cred, "ap-shanghai", clientProfile);

            IDCardOCRRequest req = new IDCardOCRRequest();
            if (StringUtil.isNotEmpty(bo.getImageUrl())){
                req.setImageUrl(bo.getImageUrl());
            }else if (StringUtil.isNotEmpty(bo.getImageBase64())){
                req.setImageBase64(bo.getImageBase64());
            }

            String dateTime = Instant.now().toString();
            IDCardOCRResponse resp = client.IDCardOCR(req);
            IdCardVo idCardVo = BeanConverUtils.convertBean(resp,IdCardVo.class);

            //腾讯云校验记录
            IdCardVerifyRecord idCardVerifyRecord=new IdCardVerifyRecord();
            idCardVerifyRecord.setRequest(JSON.toJSONString(bo));
            idCardVerifyRecord.setIsFaceVerify(OcrEnum.OcrStatus.ID_DCARD_OCR.getCode());
            idCardVerifyRecord.setResponse(IDCardOCRResponse.toJsonString(resp));
            idCardVerifyRecord.setDatetime(dateTime);
            ((TencentOCRUtil) AopContext.currentProxy()).recordNew(idCardVerifyRecord);

            return idCardVo;
        } catch (TencentCloudSDKException e) {
            System.out.println(e.toString());
            e.printStackTrace();
        }
        return null;
    }

    public BizLicenseVo bizLicenseOCR(IDOCRAuthBo bo){
        try{
            Credential cred = new Credential(idSecretId, idSecretKey);

            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint(OCRVerifyUrl);

            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);

            OcrClient client = new OcrClient(cred, "ap-shanghai", clientProfile);

            BizLicenseOCRRequest req = new BizLicenseOCRRequest();

            if (StringUtil.isNotEmpty(bo.getImageUrl())){
                req.setImageUrl(bo.getImageUrl());
            }else if (StringUtil.isNotEmpty(bo.getImageBase64())){
                req.setImageBase64(bo.getImageBase64());
            }

            String dateTime = Instant.now().toString();
            BizLicenseOCRResponse resp = client.BizLicenseOCR(req);
            BizLicenseVo bizLicenseVo = BeanConverUtils.convertBean(resp,BizLicenseVo.class);

            //校验记录
            IdCardVerifyRecord idCardVerifyRecord=new IdCardVerifyRecord();
            idCardVerifyRecord.setRequest(JSON.toJSONString(bo));
            idCardVerifyRecord.setIsFaceVerify(OcrEnum.OcrStatus.BIZLICENSE_OCR.getCode());
            idCardVerifyRecord.setResponse(BizLicenseOCRResponse.toJsonString(resp));
            idCardVerifyRecord.setDatetime(dateTime);
            ((TencentOCRUtil) AopContext.currentProxy()).recordNew(idCardVerifyRecord);

            return bizLicenseVo;
        } catch (TencentCloudSDKException e) {
            System.out.println(e.toString());
            e.printStackTrace();
        }
        return null;
    }

    public BankCardVo bankCardOCR(IDOCRAuthBo bo){
        try{
            Credential cred = new Credential(idSecretId, idSecretKey);

            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint(OCRVerifyUrl);

            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);

            OcrClient client = new OcrClient(cred, "ap-shanghai", clientProfile);

            BankCardOCRRequest req = new BankCardOCRRequest();

            if (StringUtil.isNotEmpty(bo.getImageUrl())){
                req.setImageUrl(bo.getImageUrl());
            }else if (StringUtil.isNotEmpty(bo.getImageBase64())){
                req.setImageBase64(bo.getImageBase64());
            }

            String dateTime = Instant.now().toString();
            BankCardOCRResponse resp = client.BankCardOCR(req);;
            BankCardVo bankCardVo = BeanConverUtils.convertBean(resp,BankCardVo.class);

            //校验记录
            IdCardVerifyRecord idCardVerifyRecord=new IdCardVerifyRecord();
            idCardVerifyRecord.setRequest(JSON.toJSONString(bo));
            idCardVerifyRecord.setIsFaceVerify(OcrEnum.OcrStatus.BANK_CARD_OCR.getCode());
            idCardVerifyRecord.setResponse(BankCardOCRResponse.toJsonString(resp));
            idCardVerifyRecord.setDatetime(dateTime);
            ((TencentOCRUtil) AopContext.currentProxy()).recordNew(idCardVerifyRecord);

            return bankCardVo;
        } catch (TencentCloudSDKException e) {
            System.out.println(e.toString());
            e.printStackTrace();
        }
        return null;
    }

    @Async
    public void recordNew(IdCardVerifyRecord idCardVerifyRecord) {
        idCardVerifyRecordDao.insert(idCardVerifyRecord);
    }

}
